<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能对话助手</title>
    <!-- 生产环境Vue -->
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.prod.min.js"></script>
    <!-- 安全净化 -->
    <script src="https://cdn.staticfile.org/dompurify/2.4.0/purify.min.js"></script>
    <!-- Markdown解析 -->
    <script src="https://cdn.staticfile.org/marked/4.0.2/marked.min.js"></script>
    <style>
        :root {
            --primary-color: #007AFF;
            --bg-color: #F5F5F7;
            --bot-bubble: #F1F2F4;
        }

        body {
            font-family: -apple-system, sans-serif;
            margin: 0;
            height: 100vh;
            display: flex;
            flex-direction: column;
            background: var(--bg-color);
        }

        .chat-container {
            max-width: 800px;
            margin: 0 auto;
            flex: 1;
            width: 100%;
            padding: 20px;
        }

        .message-stream {
            height: 70vh;
            overflow-y: auto;
            padding: 20px 0;
            scroll-behavior: smooth;
        }

        .message-bubble {
            max-width: 80%;
            padding: 16px 24px;
            margin: 8px 0;
            border-radius: 20px;
            background: var(--bot-bubble);
            animation: messageAppear 0.3s ease;
        }

        .markdown-content {
            line-height: 1.7;
            word-break: break-word;
        }
        .markdown-content ul {
            padding-left: 1.5em;
            list-style: disc;
            margin: 1em 0;
        }
        .markdown-content li {
            margin: 0.5em 0;
        }

        .input-area {
            padding: 20px 0;
            border-top: 1px solid #ddd;
            background: white;
        }

        .input-box {
            max-width: 800px;
            margin: 0 auto;
            display: flex;
            gap: 12px;
            align-items: center;  /* 垂直居中 */
            justify-content: center; /* 水平居中 */
        }

        textarea {
            flex: 1;
            padding: 14px 20px;
            border: 1px solid #ddd;
            border-radius: 16px;
            min-height: 56px;
            resize: none;
            font-size: 16px;
            max-width: 600px;
        }

        button {
            padding: 0 28px;
            background: var(--primary-color);
            color: white;
            border: none;
            border-radius: 12px;
            cursor: pointer;
            height: 56px;
            transition: opacity 0.2s;
        }
        button:disabled {
            background: #999;
            cursor: not-allowed;
        }

        .typing-indicator {
            display: inline-flex;
            gap: 8px;
            padding: 12px 20px;
        }
        .typing-dot {
            width: 8px;
            height: 8px;
            background: #666;
            border-radius: 50%;
            animation: typing 1.4s infinite;
        }

        @keyframes messageAppear {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        @keyframes typing {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-4px); }
        }
    </style>
</head>
<body>
<div id="app">
    <div class="chat-container">
        <div class="message-stream" ref="messageContainer">
            <div v-for="(msg, index) in messages"
                 :key="index"
                 class="message-bubble">
                <div class="markdown-content" v-html="msg.content"></div>
            </div>
            <div v-if="loading" class="message-bubble">
                <div class="typing-indicator">
                    <div class="typing-dot" style="animation-delay: 0s"></div>
                    <div class="typing-dot" style="animation-delay: 0.2s"></div>
                    <div class="typing-dot" style="animation-delay: 0.4s"></div>
                </div>
            </div>
        </div>
        <div class="input-area">
            <form class="input-box" @submit.prevent="sendMessage">
                <textarea v-model="inputText"
                          placeholder="输入您的问题..."
                          :disabled="isSubmitting"></textarea>
                <button type="submit"
                        :disabled="isSubmitting || !inputText.trim()">
                    {{ isSubmitting ? '发送中...' : '发送' }}
                </button>
            </form>
        </div>
    </div>
</div>

<script>
    // 调试模式开关
    const DEBUG_MODE = true;

    // Markdown配置
    marked.use({
        breaks: true,
        gfm: true,
        renderer: {
            list(body, ordered) {
                return ordered ?
                    `<ol class="md-list">${body}</ol>` :
                    `<ul class="md-list">${body}</ul>`;
            },
            listitem(text) {
                return `<li class="md-list-item">${text}</li>`;
            }
        }
    });

    const { createApp, ref, nextTick } = Vue;

    createApp({
        setup() {
            // 响应式状态
            const messages = ref([]);
            const inputText = ref('');
            const isSubmitting = ref(false);
            const loading = ref(false);
            const messageContainer = ref(null);
            let eventSource = null;
            let buffer = "";

            // 调试日志
            const log = (...args) => {
                if(DEBUG_MODE) console.log('[DEBUG]', new Date().toISOString(), ...args);
            }

            // 滚动到底部
            const scrollToBottom = () => {
                nextTick(() => {
                    if (messageContainer.value) {
                        messageContainer.value.scrollTop = messageContainer.value.scrollHeight;
                    }
                });
            };

            // 处理Markdown
            const parseMarkdown = (text) => {
                try {
                    const raw = marked.parse(text);
                    return DOMPurify.sanitize(raw);
                } catch (e) {
                    log('Markdown解析失败:', e);
                    return text;
                }
            };

            // SSE处理器
            const handleSSE = (userInput) => {
                const apiUrl = `http://localhost:8080/api/chat/stream?query=${encodeURIComponent(userInput)}`;
                log('正在建立SSE连接:', apiUrl);

                eventSource = new EventSource(apiUrl);
                let chunkCounter = 0;

                eventSource.onopen = () => {
                    log('SSE连接已建立，状态:', eventSource.readyState);
                };

                eventSource.onmessage = (event) => {
                    chunkCounter++;
                    const chunk = event.data;
                    log(`收到第${chunkCounter}个数据块`, {
                        size: chunk.length + ' bytes',
                        preview: chunk.substring(0, 50) + (chunk.length > 50 ? '...' : '')
                    });

                    if (chunk.includes('[DONE]')) {
                        log('收到完成信号');
                        eventSource.close();
                        isSubmitting.value = false;
                        loading.value = false;
                        return;
                    }

                    buffer += chunk;
                    messages.value[messages.value.length-1].content = parseMarkdown(buffer);
                    scrollToBottom();
                };

                eventSource.onerror = (error) => {
                    log('SSE连接错误:', {
                        readyState: eventSource.readyState,
                        error: error
                    });

                    if (eventSource.readyState === EventSource.CLOSED) {
                        log('连接正常关闭');
                    } else {
                        messages.value[messages.value.length-1].content += '<br>⚠️ 连接异常，请重试';
                    }

                    isSubmitting.value = false;
                    loading.value = false;
                    eventSource.close();
                };
            };

            // 发送消息
            const sendMessage = async () => {
                if (!inputText.value.trim()) return;

                messages.value.push(
                    { role: 'user', content: inputText.value.trim() },
                    { role: 'assistant', content: '' }
                );
                inputText.value = '';
                isSubmitting.value = true;
                loading.value = true;

                await nextTick();
                scrollToBottom();
                handleSSE(messages.value[messages.value.length-2].content);
            };

            return {
                messages,
                inputText,
                isSubmitting,
                loading,
                messageContainer,
                sendMessage
            };
        }
    }).mount('#app');
</script>
</body>
</html>